package com.hex.ds.hdrs.engine.exec;

import com.hex.ds.hdrs.center.service.CenterManager;
import com.hex.ds.hdrs.common.constant.Const;
import com.hex.ds.hdrs.common.utils.HdrsDateUtil;
import com.hex.ds.hdrs.engine.manager.LstFinishManager;
import com.hex.ds.hdrs.engine.manager.ToDoManager;
import com.hex.ds.hdrs.engine.service.DispatcherService;
import com.hex.ds.hdrs.engine.service.ProcessorService;
import com.hex.ds.hdrs.period.job.po.PeriodJob;
import com.hex.ds.hdrs.period.task.po.PeriodTask;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * @Package: com.hex.ds.hdrs.engine.exec
 * @ClassName LstFinishExec
 * @Description: 最新完成队列
 * @Author: jd.chen
 * @Date 2021/7/5 18:39
 * @Version v1.0
 **/
@Slf4j
@EnableScheduling
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LstFinishExec {

    private final LstFinishManager lstFinishManager;
    private final CenterManager centerManager;
    private final ProcessorService processorService;
    private final DispatcherService dispatcherService;

    private final ToDoManager toDoManager;

    /**
     * 增量
     */
//    @Scheduled(fixedDelayString = "${scheduled.latestFinish.addFixedDelay}",initialDelayString = "${scheduled.latestFinish.addInitialDelay}")
    private void addExec(){
        log.debug("加载器执行增量【LatestFinishExec.addExec】开始===》【{}】", HdrsDateUtil.getCurTs());
        if (!this.isCanLoad(Const.ADD_LST_FNS_MARK)) {
            return;
        }
        try {
            //2. 增量处理
            this.addDeal();
        } catch (Exception e) {
            log.error("最新完成队列处理--增量【LatestFinishExec.add】【异常】:{}" , e.getMessage(), e);
        } finally {
            //4. 打标恢复
            toDoManager.setMark(Const.FREE_LOADER_MARK);
            log.debug("最新完成队列处理--增量【LatestFinishExec.add】结束《===【{}】", HdrsDateUtil.getCurTs());
        }
    }

    /**
     * 全量
     */
//    @Scheduled(fixedDelayString = "${scheduled.latestFinish.allFixedDelay}",initialDelayString = "${scheduled.latestFinish.allInitialDelay}")
    private void allExec(){
        log.debug("加载器执行全量【LatestFinishExec.allExec】开始===》【{}】", HdrsDateUtil.getCurTs());
        if (!this.isCanLoad(Const.ALL_LST_FNS_MARK)) {
            return;
        }
        try {
            //2. 内存化
            this.allDeal();
        } catch (Exception e) {
            log.error("最新完成队列处理--全量【LatestFinishExec.all】【异常】:{}" , e.getMessage(), e);
        } finally {
            this.finalDeal();
            log.debug("最新完成队列处理--全量【LatestFinishExec.all】结束《===【{}】", HdrsDateUtil.getCurTs());
        }
    }

    /**
     * 最新完成队列是否可加载
     *
     * @return
     */
    public boolean isCanLoad(String mark) {
        log.info("最新完成队列是否可加载【LatestFinishExec.isCanLoad】=======》");
        if (!centerManager.isCanDeal()) {
            log.warn("【该中心不是Master】");
            return false;
        }
        if (!toDoManager.loaderMark(mark)) {
            log.warn("【最新完成队列正忙或未初始化成功】");
            return false;
        }
        return true;
    }

    /**
     * 全量  finally所需处理
     */
    public void finalDeal() {
        log.info("全量  finally所需处理【LatestFinishExec.finalDeal】=======》");
        //1. 分发器启用
        this.dispatcherService.continueDispatcher();
        //2. 处理器启用
        this.processorService.continueProcess();
        //3. 恢复打标
        toDoManager.setMark(Const.FREE_LOADER_MARK);
    }

    /**
     * 增量处理
     */
    private void addDeal() {
        log.debug("增量处理【LatestFinishExec.addDeal】开始=======》");

        log.debug("【1】获取DB中增量的作业/任务--开始");
        List<PeriodJob> jobList = lstFinishManager.getAddJobList();
        List<PeriodTask> taskList = lstFinishManager.getAddTaskList();
        log.debug("【1】获取DB中增量的作业/任务--结束");

        log.debug("【2】合并到最新完成队列--开始");
        lstFinishManager.mergeLstJob(jobList);
        lstFinishManager.mergeLstTask(taskList);
        log.debug("【2】合并到最新完成队列--结束");

        log.debug("增量处理【LatestFinishExec.addDeal】结束《=======");
    }


    /**
     * 全量处理
     */
    private void allDeal() {
        log.debug("全量处理【LatestFinishExec.allDeal】开始=======》");

        log.debug("【1】获取DB中增量的作业/任务--开始");
        Map<String, PeriodJob> jobMap = lstFinishManager.getAllJobMap();
        Map<String, PeriodTask> taskMap = lstFinishManager.getAllTaskMap();
        log.debug("【1】获取DB中增量的作业/任务--结束");

        log.debug("【2】分发器、处理器停用--开始");
        dispatcherService.stopDispatcher();
        processorService.stopProcess();
        log.debug("【2】分发器、处理器停用--结束");

        log.debug("【3】做锁切换--开始");
        lstFinishManager.addJobTaskMap(jobMap, taskMap);
        log.debug("【3】做锁切换--结束");

        log.debug("【4】delta中的数据合并--开始");
        lstFinishManager.mergeDelta();
        log.debug("【4】delta中的数据合并--结束");

        log.debug("全量处理【LatestFinishExec.allDeal】结束《=======");
    }
}
